package com.genexususa.eo.google.connection;

import com.genexususa.eo.google.exceptions.ConnectionException;
import com.google.api.ads.adwords.lib.client.AdWordsSession;
import com.google.api.ads.common.lib.auth.OfflineCredentials;
import com.google.api.ads.common.lib.conf.ConfigurationLoadException;
import com.google.api.ads.common.lib.exception.OAuthException;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.client.auth.oauth2.Credential;
import org.apache.log4j.Logger;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;

public class SessionController {

    private static SessionController Instance = new SessionController();

    private final static Logger log = Logger.getLogger(SessionController.class);


    private HashMap<String, Session> _sessions = new HashMap<String, Session>();

    public static SessionController getInstance() {
        return Instance;
    }

    private SessionController() {

    }


    public void AddSession(String clientId, AdWordsSession session) {

        if (_sessions.containsKey(clientId)) {
            int actualInstances = _sessions.get(clientId).GetInstances();

            _sessions.get(clientId).SetInstances(actualInstances++);
        } else {

            Session s = new Session();
            s.SetInstances(1);
            s.SetSession(session);

            _sessions.put(clientId, s);
        }
    }


    public AdWordsSession GetSession(String clientId) throws ConnectionException {


        if (_sessions.containsKey(clientId))
            return _sessions.get(clientId).GetSession();
        else {
            try {

                Credential oAuth2Credential = new OfflineCredentials.Builder()
                        .forApi(OfflineCredentials.Api.ADWORDS)
                        .fromFile()
                        .build()
                        .generateCredential();

                AdWordsSession session = new AdWordsSession.Builder()
                        .fromFile()
                        .withOAuth2Credential(oAuth2Credential)
                        .build();

                session.setClientCustomerId(clientId);


                Session s = new Session();
                s.SetSession(session);
                s.SetInstances(1);

                log.info("Session created, clientId: " + clientId);
                _sessions.put(clientId, s);
                return session;

            } catch (ValidationException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                log.error("Error in session controller: ValidationException");

                StringWriter errors = new StringWriter();
                e.printStackTrace(new PrintWriter(errors));
                log.error(errors.toString());
                return null;
            } catch (ConfigurationLoadException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                log.error("Error in session controller: ConfigurationLoadException");

                StringWriter errors = new StringWriter();
                e.printStackTrace(new PrintWriter(errors));
                log.error(errors.toString());
                return null;
            } catch (OAuthException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                log.error("Error in session controller: OauthException");

                StringWriter errors = new StringWriter();
                e.printStackTrace(new PrintWriter(errors));
                log.error(errors.toString());
                throw new ConnectionException();
            }
        }

    }

    public void RemoveSession(String clientId) {

        if (_sessions.containsKey(clientId)) {

            Session s = _sessions.get(clientId);

            if (s.GetInstances() == 1) {

                _sessions.remove(clientId);
                log.info("Session removed, clientId: " + clientId + ", instances: " + s.GetInstances());
            } else {

                s.SetInstances(s.GetInstances() - 1);
                _sessions.remove(clientId);
                log.info("Session removed, clientId: " + clientId + ", instances: " + s.GetInstances());
                _sessions.put(clientId, s);
            }


        }
    }

}
